🐛 selfMetadata 支持空覆盖:修复匹配/排除/标签/运行时机「删除即复活」#1579
Conversation
|
PR 当前针对“重置匹配规则”的修复方向是正确的。 当 不过审查时发现,同一根因下还有一条遗漏路径:逐条删除规则,直到列表为空。 原来的实现中,删除最后一项后会调用: setMatchList(kind, [])这里传给后端的是空数组,而不是 但前端此时仍显示空列表,并写入 已在 const override = next?.length ? next : undefined这样,无论是点击重置,还是逐条删除到空列表,都会走相同的“删除覆盖并回落原始 metadata”逻辑。 修复过程按照仓库的 TDD 规范进行:先补充失败用例,复现“删除最后一项后前端显示为空,但后端已经回落原始规则”的问题,再修改实现。新增测试为:
另外还发现几处同类问题,但与本 PR 的修改范围关系较弱,因此没有一并处理,只建议后续单独跟进:
|
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@CodFrm 那4个交给你了 |
根因:selfMetadataUpdate 把空集合一律当成「删除覆盖」,导致用户永远无法
显式清空脚本自带的 tag / match / exclude——删到空后覆盖被删、生效值回落
metadata,刷新即复活。改为区分 undefined(撤销覆盖) 与空集合(显式清空):
- selfMetadataUpdate 接受 Set|undefined,空集合持久化为 []
- resetMatch/resetExclude/updateMetadata RPC 边界区分 undefined 与 []
(excludeUrl 由根因修复自动受益,popup 取消最后一条排除不再复活)
- SettingsPane 前端对齐:重置传 undefined、编辑传数组;删除最后一项 = 显式清空
- 修复 onRunAt 选非 early-start 时下拉框回弹 early-start(空数组被当真值);
run-in/run-at 选「默认」改传 undefined 撤销覆盖,保持行为不变
- 重写 8 个语言包 after_deleting_{match,exclude}_item 过时且自相矛盾的文案
对应 review 提出的 4 项遗漏路径(标签/popup 排除/文案/run-at)
|
4 项已在本 PR 一并处理,思路是走根因而非继续在前端对齐:
改动:
测试:新增 |
Checklist / 检查清单
Description / 描述
脚本设置里用户对
@match/@exclude/@tag/@run-at等元数据的覆盖存在selfMetadata,用来在不改脚本源码的前提下自定义生效规则。根因:
selfMetadataUpdate(src/app/service/service_worker/utils.ts)把「空集合」一律解释为「删除覆盖」,导致后端根本无法表示「用户显式清空」——空覆盖等价于「没有覆盖」,生效值必然回落脚本自带metadata。因此凡是「删到空」的操作,刷新后规则都会复活,用户永远无法清空脚本自带的规则。而
getCombinedMeta的v ? [...v] : undefined对[](真值)本就能正确覆盖,DAO / 备份 / 同步链路也都支持空覆盖(导入 VM/TM 备份时self_metadata.ts今天就会写出match: []),唯独这个函数拒收——这才是本质,所以走根因修复而非继续在前端对齐。改动:
selfMetadataUpdate(script, key, Set | undefined):undefined= 撤销覆盖(回落脚本自带 metadata),空集合 = 持久化为[](显式清空),两者语义不再互相替代。resetMatch/resetExclude/updateMetadata(+client.ts)区分undefined与[](原来new Set(x || [])把两者塌成同一个空集)。SettingsPane:重置传undefined、编辑传数组;「删除最后一项」= 用户显式清空(不再复活脚本自带规则)。onRunAt选非 early-start 时下拉框回弹「early-start」的可见 bug(乐观写入early-start: [],而runAt用真值判断 →[]被当真值);run-in/run-at选「默认」改传undefined撤销覆盖,行为不变。after_deleting_{match,exclude}_item——旧文案描述的「删除后自动加回」行为已不存在,其中 exclude 那条还自相矛盾(「匹配项…添加到排除项」);新文案描述当前语义:编辑即覆盖、点「重置」恢复脚本自带规则。覆盖的场景(对应 review 提出的 4 项遗漏路径):
@tag。@exclude(由根因修复自动受益,excludeUrl无需改)。测试(TDD,先写失败用例再修):
script.test.ts:excludeUrl/resetMatch/resetExclude/updateMetadata的undefinedvs[]语义。utils.test.ts:区分「撤销覆盖」与「保存空覆盖」,并修正钉住旧语义的用例。SettingsPane.test.tsx:反转「删除最后一项应回落」用例为「应显式清空」,新增运行时机不回弹 / 选「默认」传undefined用例。受影响套件 +
backup/synchronize/runtime/popup全绿;tsc --noEmit、ESLint、Prettier 均通过。Screenshots / 截图
N/A(逻辑修复,无 UI 视觉变化)